package so.sao.code.service.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import so.sao.code.dto.request.CodeSeqment;
import so.sao.code.service.domain.ValidateUtils;
import so.sao.code.service.domain.entity.EnterpriseInfo;
import so.sao.code.service.domain.entity.RangeActivation;
import so.sao.code.service.domain.entity.SeqmentCustomField;
import so.sao.code.service.domain.entity.TagBatch;
import so.sao.code.service.domain.entity.TagBatchConfig;
import so.sao.code.service.domain.entity.TagBatchDownloadLog;
import so.sao.code.service.domain.entity.TagOperationLog;
import so.sao.code.service.domain.entity.TagScrap;
import so.sao.code.service.domain.event.RangeActivationActiveEvent;
import so.sao.code.service.domain.service.RangeActivativeDomainService;
import so.sao.code.service.infrastructure.SessionContext;
import so.sao.code.service.infrastructure.annotation.Permission;
import so.sao.code.service.infrastructure.dozer.Mapper;
import so.sao.code.service.infrastructure.enums.ActivationMethod;
import so.sao.code.service.infrastructure.enums.CodeMessage;
import so.sao.code.service.infrastructure.enums.OPERATION;
import so.sao.code.service.infrastructure.enums.ROLE;
import so.sao.code.service.infrastructure.enums.TAG_SCRAP_TYPE;
import so.sao.code.service.infrastructure.enums.TagRangeStatus;
import so.sao.code.service.infrastructure.model.vo.RangeActivationVO;
import so.sao.code.service.infrastructure.model.vo.SeqmentCustomFieldVO;
import so.sao.code.service.infrastructure.model.vo.TagDetailVO;
import so.sao.code.service.infrastructure.model.vo.TagOperationLogVO;
import so.sao.code.service.infrastructure.model.vo.TagStatisticsVO;
import so.sao.code.service.repository.EnterpriseInfoDao;
import so.sao.code.service.repository.RangeActivationDao;
import so.sao.code.service.repository.SeqmentCustomFieldDao;
import so.sao.code.service.repository.TagBatchConfigDao;
import so.sao.code.service.repository.TagBatchDao;
import so.sao.code.service.repository.TagBatchDownloadLogDao;
import so.sao.code.service.repository.TagOperationLogDao;
import so.sao.code.service.service.RangeActivationService;
import so.sao.code.service.service.TagBatchService;
import so.sao.code.service.service.TagScrapService;
import so.sao.code.service.service.TagStatusInfoService;
import so.sao.data.feign.client.EnterpriseClient;
import so.sao.ffw.dto.request.TagEseStatusRequest;
import so.sao.ffw.dto.response.TagEseStatusResponse;
import so.sao.ffw.feign.client.TagBatchReportClient;
import so.sao.ffw.feign.client.TagRangeActivationClient;
import so.sao.nosql.datastore.enums.tag.TagStatus;
import so.sao.sso.common.CommonConstants;
import so.sao.sso.feign.dto.UserDTO;
import so.sao.top.core.util.rest.RestException;

/**
 * Created by Administrator on 2017/6/27.
 */
@Service
public class RangeActivationServiceImpl implements RangeActivationService {

	@Autowired
	TagBatchDao tagBatchDao;
	@Autowired
	RangeActivationDao rangeActivationDao;
	@Autowired
	EnterpriseClient enterprisesClient;
	@Autowired
	TagBatchReportClient tagBatchReportClient;
	@Autowired
	TagOperationLogDao tagOperationLogDao;
	@Autowired
	TagBatchConfigDao tagBatchConfigDao;
	@Autowired
	TagBatchService tagBatchService;
	@Autowired
	TagStatusInfoService tagStatusInfoService;
	@Autowired
	TagScrapService tagScrapService;
	@Autowired
	RangeActivativeDomainService rangeActivativeDomainService;
	@Autowired
	SessionContext context;
	@Autowired
	TagBatchDownloadLogDao tagBatchDownloadLogDao;
	@Autowired
	SeqmentCustomFieldDao seqmentCustomFieldDao;
	@Autowired
	TagRangeActivationClient tagRangeActivationClient;
	@Autowired
	EnterpriseClient enterpriseClient;

	/**
	 * 分段
	 *
	 * @return
	 */
	@Override
	public RangeActivationVO doSegment(CodeSeqment codeSeqment) {
		Long batchId = codeSeqment.getBatchId();
		Long start = codeSeqment.getStart();
		Long end = codeSeqment.getEnd();
		TagBatch tagBatch = tagBatchDao.findOne(batchId);
		if (!context.CURRECT_USER.getEseId().equals(1L)
				&& !tagBatch.getEseId().equals(context.CURRECT_USER.getEseId())) {
			throw new RestException(HttpStatus.BAD_REQUEST, CodeMessage.InvalidRequest);
		}
		RangeActivation rangeActivation = new RangeActivation();
		rangeActivation.setTagBatchId(batchId);
		if (end < start) {
			throw new RestException(HttpStatus.BAD_REQUEST, CodeMessage.StratingMustBeLessThenEnding);
		}
		rangeActivation.setSeqnumEnd(end);
		rangeActivation.setSeqnumStart(start);
		rangeActivativeDomainService.filterRange(tagBatch, rangeActivation);
		RangeActivation range = rangeActivationDao.save(rangeActivation);
		RangeActivationVO rangeActivationVO = Mapper.map(range, RangeActivationVO.class);
		logAction(new RangeActivationActiveEvent(tagBatch, rangeActivation, OPERATION.SEGMENT));
		return rangeActivationVO;

	}

	/**
	 * 綁定参数
	 */
	@Transactional
	@Override
	public void doBind(CodeSeqment codeSeqment) {
		RangeActivation rangeActivation = rangeActivationDao.findOne(codeSeqment.getRangeId());
		TagBatch tagBatch = tagBatchDao.findOne(rangeActivation.getTagBatchId());
		if (!context.CURRECT_USER.getEseId().equals(1L)
				&& !tagBatch.getEseId().equals(context.CURRECT_USER.getEseId())) {
			throw new RestException(HttpStatus.BAD_REQUEST, CodeMessage.InvalidRequest);
		}
		if (codeSeqment.getBrandId() != null || !codeSeqment.getBrandId().equals("")) {
			rangeActivation.setBrandId(codeSeqment.getBrandId());
		}
		if (codeSeqment.getProductId() != null || !codeSeqment.getProductId().equals("")) {
			rangeActivation.setProductId(codeSeqment.getProductId());
		}
		if (codeSeqment.getFranchiserId() != null || !codeSeqment.getFranchiserId().equals("")) {
			rangeActivation.setFranchiserId(codeSeqment.getFranchiserId());
		}
		if (codeSeqment.getFactoryId() != null || !codeSeqment.getFactoryId().equals("")) {
			rangeActivation.setFactoryId(codeSeqment.getFactoryId());
		}
		rangeActivationDao.save(rangeActivation);
		seqmentCustomFieldDao.deleteByrangeId(rangeActivation.getId());
		if (codeSeqment.getSeqmentCustomFieldRequestList() != null
				&& codeSeqment.getSeqmentCustomFieldRequestList().size() > 0) {
			List<SeqmentCustomField> SeqmentCustomFieldIn = Mapper
					.mapList(codeSeqment.getSeqmentCustomFieldRequestList(), SeqmentCustomField.class);
			for (SeqmentCustomField seqmentCustomField : SeqmentCustomFieldIn) {
				seqmentCustomField.setRangeId(codeSeqment.getRangeId());
				seqmentCustomFieldDao.save(seqmentCustomField);
			}
		}
		logAction(new RangeActivationActiveEvent(tagBatch, rangeActivation, OPERATION.BIND));
	}

	/**
	 * 激活（发布云端）
	 */
	@Override
	public void doActive(CodeSeqment codeSeqment) {
		RangeActivation rangeActivation = rangeActivationDao.findOne(codeSeqment.getRangeId());
		TagBatch tagBatch = tagBatchDao.findOne(rangeActivation.getTagBatchId());
		ValidateUtils.tagActivecheck(context.CURRECT_USER, tagBatch);
		rangeActivation.setActivationMethod(codeSeqment.getActivationMethod());
		rangeActivation.setActivationParam(codeSeqment.getActivationParam());
		rangeActivationDao.save(rangeActivation);
		rangeActivativeDomainService.activeRangeActivation(rangeActivation, tagBatch);
	}

	/**
	 * 撤销绑定
	 */
	@Permission(role = ROLE.ADMIN)
	@Override
	public void undoBind(long id) {
		RangeActivation rangeActivation = rangeActivationDao.findOne(id);
		rangeActivation.setStatus(TagRangeStatus.UNACTIVATE.getValue());
		rangeActivationDao.save(rangeActivation);
		TagBatch tagBatch = tagBatchDao.findOne(rangeActivation.getTagBatchId());
		// publish(new RangeActivationActiveEvent(tagBatch, rangeActivation,
		// OPERATION.UNACTIVAE));
		rangeActivativeDomainService.activeToCloud(rangeActivativeDomainService
				.createTagRangeActivationMessage(tagBatch, rangeActivation, TagStatus.NOT_ACTIVATE));
	}

	public void tagActiveTask() {
		List<Integer> methods = new ArrayList<>();
		methods.add(ActivationMethod.Custom.getValue());
		methods.add(ActivationMethod.Delay.getValue());
		List<RangeActivation> list = rangeActivationDao
				.findByStatusAndActivationMethodIn(TagRangeStatus.UNACTIVATE.getValue(), methods);
		// List<TagTask> list =
		// tagTaskDao.findByTypeAndStatus(RangeActivation.class.getName(),
		// TASK_STATUS.UNDO);
		for (RangeActivation rangeActivation : list) {
			try {
				TagBatch tagBatch = tagBatchDao.findOne(rangeActivation.getTagBatchId());
				if (tagBatch.getTagBatchConfigId() == null || tagBatch.getTagBatchConfigId().longValue() == 0) {
					continue;
				}
				rangeActivativeDomainService.activeRangeActivation(rangeActivation, tagBatch);
			} catch (Exception e) {

			}
		}
	}

	@Autowired
	EnterpriseInfoDao enterpriseInfoDao;

	@Override
	public TagStatisticsVO geTagStatistics(UserDTO user, long eseId) {
		if (!user.getEseId().equals(eseId))
			throw new RestException(HttpStatus.BAD_REQUEST, CodeMessage.InvalidRequest);
		EnterpriseInfo enterpriseInfo = enterpriseInfoDao.findByEseId(eseId);
		// EnterpriseDTO enterpriseDto =
		// enterprisesClient.findTopEnterprise(eseId);
		TagStatisticsVO tagStatisticsVO = new TagStatisticsVO();
		if (CommonConstants.SYSTEM_INNER_ESEID.equals(user.getEseId())) {
			tagStatisticsVO.setBatchCount(tagBatchDao.count());
			tagStatisticsVO.setGeneratedCodeCount(Optional.ofNullable(tagBatchDao.sumCode()).orElse(0L));
		} else {
			tagStatisticsVO.setBatchCount(tagBatchDao.countBatchByEseId(eseId));
			tagStatisticsVO.setGeneratedCodeCount(enterpriseInfo.getCreatedCount());
			// tagStatisticsVO.setGeneratedCodeCount(Optional.ofNullable(tagBatchDao.sumTagCountByEseId(eseId)).orElse(0L));
		}
		// long usedCount =
		// enterpriseInfo.getCreatedCount();//Optional.ofNullable(tagBatchDao.sumTagCountByEseId(enterpriseDto.getId())).orElse(0L);
		tagStatisticsVO.setRemainUseCodeCount(enterpriseInfo.getUpCount());
		TagEseStatusRequest tagbatchRequest = new TagEseStatusRequest();
		tagbatchRequest.setEseId(eseId);
		tagbatchRequest.setStatus(TagStatus.ACTIVATE.getStatus());
		TagEseStatusResponse tagBatchResponse = tagBatchReportClient.tagEseStatusCount(tagbatchRequest);
		tagStatisticsVO.setActivatedCodeCount(tagBatchResponse.getCount());
		tagbatchRequest.setStatus(TagStatus.INVALID.getStatus());
		tagBatchResponse = tagBatchReportClient.tagEseStatusCount(tagbatchRequest);
		List<TagScrap> tagScrapList=tagScrapService.findTagScrapInfoByScrapType(TAG_SCRAP_TYPE.SCRAPBYBOX);
		Long res=tagScrapList.stream().mapToLong(TagScrap::getTagScrapCount).sum();
		Long packageCount=tagScrapList.stream().mapToLong(TagScrap::getTagScrapCount).count();
		tagStatisticsVO.setDisableCodeCount(tagBatchResponse.getCount()+res-packageCount);
		return tagStatisticsVO;
	}

	@Override
	public void pushSupplyChain(long batchId) {
		TagBatch tagBatch = Optional.ofNullable(tagBatchDao.findOne(batchId))
				.orElseThrow(() -> new RestException(HttpStatus.BAD_REQUEST, CodeMessage.InvalidRequest));
		rangeActivativeDomainService.supplyChainActive(tagBatch);
	}

	@Override
	public List<RangeActivationVO> findTagBatchSegmentInfo(long tagBatchId) {
		List<RangeActivation> result = rangeActivationDao.findByTagBatchId(tagBatchId);
		List<RangeActivationVO> list = Mapper.mapList(result, RangeActivationVO.class);
		if (list.size() == 0) {
			list = new ArrayList<RangeActivationVO>();
		}
		return list;
	}

	@Override
	public RangeActivationVO findSegmentInfoByRangId(long rangId) {
		RangeActivation rangeActivation = rangeActivationDao.findById(rangId);
		RangeActivationVO rangeActivationVO = Mapper.map(rangeActivation, RangeActivationVO.class);
		List<SeqmentCustomField> seqmentCustomField = seqmentCustomFieldDao.findByrangeId(rangId);
		List<SeqmentCustomFieldVO> list = Mapper.mapList(seqmentCustomField, SeqmentCustomFieldVO.class);
		rangeActivationVO.setSeqmentCustomFieldList(list);
		return rangeActivationVO;
	}

	/**
	 * 获取批次打印消息
	 */
	public TagDetailVO detail(Long tagBatchId) throws Exception {
		TagDetailVO vo = new TagDetailVO();
		TagBatch tagBatch = Optional.ofNullable(tagBatchDao.findOne(tagBatchId))
				.orElseThrow(() -> new RestException(HttpStatus.BAD_REQUEST, CodeMessage.InvalidRequest));
		if (!context.CURRECT_USER.getEseId().equals(1L)
				&& !tagBatch.getEseId().equals(context.CURRECT_USER.getEseId())) {
			throw new RestException(HttpStatus.BAD_REQUEST, CodeMessage.InvalidRequest);
		}
		if (tagBatch.getTagBatchConfigId() != 0L) {
			vo.setZipPassword(tagBatch.getZipPassword());
			// String filePath =
			// tagBatchService.downloadTagBatchPrintFile(tagBatchId);
			// vo.setUrl(filePath);
			List<TagBatchDownloadLog> tagBatchDownloadLog = tagBatchDownloadLogDao.findBytagBatchId(tagBatchId);
			if (tagBatchDownloadLog.size() != 0) {
				String md5 = tagBatchDownloadLog.stream().findFirst().get().getMD5();
				vo.setMD5(md5);
			}
		}
		vo.setSeqnumEnd(tagBatch.getSeqnumEnd() + "");
		vo.setSeqnumStart(tagBatch.getSeqnumStart() + "");
		TagBatchConfig config = Optional.ofNullable(tagBatchConfigDao.findByTagBatchId(tagBatchId))
				.orElse(new TagBatchConfig());
		List<TagOperationLog> logs = tagOperationLogDao.findByTagBatchId(tagBatchId);
		List<TagOperationLogVO> vos = logs.stream().map(item -> {
			TagOperationLogVO tagOperationLogVO = new TagOperationLogVO();
			BeanUtils.copyProperties(item, tagOperationLogVO);
			String[] result = item.getRange().split("-");
			tagOperationLogVO.setCodeCount(Long.parseLong(result[1]) - Long.parseLong(result[0]) + 1l);
			return tagOperationLogVO;
		}).collect(Collectors.toList());
		BeanUtils.copyProperties(config, vo);
		vo.setTagOperationLogVOs(vos);
		vo.setTagBatchId(tagBatchId);
		return vo;
	}

	public void logAction(RangeActivationActiveEvent event) {
		UserDTO user = context.CURRECT_USER;
		RangeActivation rangeActivation = event.getRangeActivation();
		String action = event.getOperation().getName();
		TagOperationLog log = new TagOperationLog(rangeActivation.getTagBatchId(), "管理端", action,
				rangeActivation.getSeqnumStart() + "-" + rangeActivation.getSeqnumEnd(), user.getUsername());
		tagOperationLogDao.save(log);
	}

	/**
	 * 标签登记 并 按条件激活(已废弃)
	 * 
	 * @throws Exception
	 */
	/*
	 * @Transactional
	 * 
	 * @Override public void bindTag(UserDTO user, RangeActivationRequest
	 * request) throws RestException { request.getBatchs().forEach(item -> {
	 * TagBatch tagBatch = tagBatchDao.findOne(item.getId());
	 * ValidateUtils.tagActivecheck(user, tagBatch); RangeActivation
	 * rangeActivation = mappingTo(false, request, tagBatch);
	 * rangeActivationDao.save(rangeActivation); if
	 * (request.getActivationMethod() == 0) return;
	 * rangeActivativeDomainService.activeRangeActivation(rangeActivation,
	 * tagBatch); }); }
	 */

	/*@Override
	public void doActiveByScan(ScanActiveRequest scanActiveRequest) throws Exception {
		TagStatusInfoDto tagStatusInfo = tagStatusInfoService.getTagStatusInfoBy(scanActiveRequest.getCodeUrl());
		TagBatch tagBatch = tagBatchDao.getTagBatchBySeqNum(tagStatusInfo.getSeqNum());
		EnterpriseDTO enterprise = enterpriseClient.findById(tagBatch.getEseId());
		Optional<List<DistributionSysRes>> res = Optional
				.ofNullable(cRMFeignClient.getResource(enterprise.getCode(), scanActiveRequest.getOpenId()));
		if (res.isPresent()) {
			TagRangeActivationMessage message = new TagRangeActivationMessage();
			message.setDomain(tagBatch.getDomain());
			message.setSeqnumStart(tagStatusInfo.getSeqNum());
			message.setSeqnumEnd(tagStatusInfo.getSeqNum());
			message.setSubDomain(tagBatch.getSubDomain());
			message.setTagBatchId(tagBatch.getId());
			message.setStatus(TagStatus.ACTIVATE.getStatus());
			tagRangeActivationClient.tagRangeActivationMessageToQueue(message);
		} else {

		}
	}*/

	/***
	 * 批量激活
	 */
	/*
	 * @Transactional public void mulitBindTag(UserDTO user,
	 * RangeActivationRequest request) throws RestException {
	 * checkMutilBatch(request); request.getBatchs().forEach(item -> { TagBatch
	 * tagBatch = tagBatchDao.findOne(item.getId());
	 * ValidateUtils.tagActivecheck(user, tagBatch); RangeActivation
	 * rangeActivation = mappingTo(true, request, tagBatch);
	 * rangeActivationDao.save(rangeActivation); if
	 * (request.getActivationMethod() == 0) return;
	 * rangeActivativeDomainService.activeRangeActivation(rangeActivation,
	 * tagBatch); }); }
	 */

	/*
	 * private void checkMutilBatch(RangeActivationRequest request) { if
	 * (request.getBatchs().stream().map(item ->
	 * item.getEseId()).distinct().count() > 1) { throw new
	 * RestException(HttpStatus.BAD_REQUEST, CodeMessage.NOTINONEENTERPRISE); }
	 * if (request.getBatchs().stream().map(item ->
	 * item.getType()).distinct().count() > 1) { throw new
	 * RestException(HttpStatus.BAD_REQUEST, CodeMessage.NOTINONEBATCHTYPE); } }
	 */
	/**
	 * 二期可以分步骤
	 */
	/*
	 * private RangeActivation mappingTo(boolean isMutil, RangeActivationRequest
	 * request, TagBatch tagBatch) { RangeActivation rangeActivation =
	 * Mapper.map(request, RangeActivation.class);
	 * rangeActivation.setSeqnumEnd(request.getEndNum());
	 * rangeActivation.setSeqnumStart(request.getStartNum()); // 激活已存在码段 只能但批次
	 * 二期可以分开 if (request.getRangeId() != 0) { rangeActivation =
	 * rangeActivationDao.findOne(request.getRangeId()); } else { if (!isMutil)
	 * rangeActivativeDomainService.filterRange(tagBatch, rangeActivation); } if
	 * (isMutil) { rangeActivativeDomainService.mulitDefaultSequNum(tagBatch,
	 * rangeActivation); }
	 * rangeActivation.setAll(rangeActivativeDomainService.isAllAcitve(tagBatch,
	 * rangeActivation)); rangeActivation.setTagBatchId(tagBatch.getId());
	 * rangeActivation.setProductId(request.getProductId());
	 * rangeActivation.setFranchiserId(request.getFranchiserId());
	 * rangeActivation.setEseId(tagBatch.getEseId());
	 * rangeActivation.setActivationMethod(request.getActivationMethod());
	 * rangeActivation.setActivationParam(request.getActivationParam()); return
	 * rangeActivation; }
	 */
}
